/* 
 * 
 * Author: Jakub Krajniak (c) 2006-2007
 * Contact: jkrajniak@gmail.com
 * Licence: GPL
 *
 * 
 * This program try to build Mealy automate from filtron's description
 * It's support only manual creating. Automating process probably would
 * be support in future version. 
 * 
 * Some comments for source are in polish. Very sorry for that unconvince. 
 * If you have question, send mail to me.
 * 
*/

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ZedGraph;
using System.Text.RegularExpressions;

namespace Filtron
{
    public partial class Form1 : Form
    {
        bool new_filtron = false;
        Filtron L;
        List<string[]> filtroniasty;
        Automat A;
        int automateCreatingStep = 0;
        int filtron_line = 0;
        int filtron_symbol = 0;
        int current_state = 0;
        bool stop = true;
        bool stop_while = false;
        bool filtron_edited = false;
        bool filtronFromFile = false;
        OperationSet hfffOperation;
        List<Regex> extinctionRegex = new List<Regex>();
        

        public Form1()
        {
            InitializeComponent();
            filtronGrid.ColumnCount = Convert.ToInt32(filtronGridX.Value);
        }
        /// <summary>
        /// Columns
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void numericUpDown2_ValueChanged(object sender, EventArgs e)
        {

        }

        private void filtronGridX_MouseClick(object sender, MouseEventArgs e)
        {

        }
        private void filtronGridY_ValueChanged(object sender, EventArgs e)
        {

        }
        private void filtronGridY_MouseClick(object sender, MouseEventArgs e)
        {

        }

        private void filtronGridY_ValueChanged_1(object sender, EventArgs e) // rows
        {
            if (!filtronFromFile)
            {
                object[] rw = new object[filtronGrid.ColumnCount];
                    //rw.SetValue(" ", 0);
                for (int i = 0; i < filtronGrid.ColumnCount; i++)
                    rw[i] = 0;
                if (filtronGridY.Value > filtronGrid.Rows.Count)
                    filtronGrid.Rows.Add(rw);
                else
                    filtronGrid.Rows.RemoveAt(Convert.ToInt32(filtronGridY.Value));
            }
        }
        private void filtronGridX_ValueChanged(object sender, EventArgs e) // columns
        {
            if (!filtronFromFile)
            {

                filtronGrid.ColumnCount = Convert.ToInt32(filtronGridX.Value);
                foreach (DataGridViewRow r in filtronGrid.Rows)
                {
                    r.Cells[filtronGrid.ColumnCount - 1].Value = 0;
                }
            }
        }
        //------------------------------------------------------------------------------

        private DialogResult uwaga(string st)
        {
            return MessageBox.Show(st, "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
        }

        private DialogResult pytanie(string st)
        {
            return MessageBox.Show(st, "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
        }

        private void resetAutomate()
        {

        }

        private void fillFiltron()
        {
            filtroniasty = new List<string[]>();
            foreach (DataGridViewRow rr in filtronGrid.Rows)
            {
                List<string> ra = new List<string>();
                foreach (DataGridViewCell c in rr.Cells)
                {
                    if (c.Value != null)
                        ra.Add(c.Value.ToString());
                }
                filtroniasty.Add(ra.ToArray());
            }
            try
            {
                L = new Filtron(filtroniasty);
            }
            catch (MyErrors er)
            {
                uwaga("Something wrong with defined filtron\n" + er.Message);
                throw er;
            }

        }

        private void setFiltron()
        {

            if (new_filtron && filtronClass.SelectedIndex == 1)
            {
                fillFiltron();
                A.MaxStates = L.MaxSymbol;
                stop = true;
                filtronClass.Enabled = true;
                if (hfffOperation.StateCount < L.MaxSymbol)
                {
                    for (int i = hfffOperation.StateCount + 1; i <= L.MaxSymbol; i++)
                    {
                        cefamHFFFGrid.Columns.Add("cefam_col_" + i.ToString(), L.ABC.code(i));
                        DataGridViewRow rr = new DataGridViewRow();
                        rr.HeaderCell.Value = "h" + L.ABC.code(i) + "=";
                        rr.DefaultCellStyle.BackColor = Color.White;
                        cefamHFFFGrid.Rows.Insert(i, rr);
                    }
                    //hfffOperation.StateCount = L.MaxSymbol;
                    hfffOperation.changeSettings(Convert.ToInt32(kSegment.Value), L.MaxSymbol);
                    automateActivateSymbolsFill();
                }
            }
            if (filtronClass.SelectedIndex == 0 && new_filtron == true)
            {
                int prevCont = L.MaxSymbol;
                fillFiltron();
                A.MaxStates = L.MaxSymbol;
                filtron_line = 0;
                filtron_symbol = 0;
                for (int i = prevCont+1; i <= L.MaxSymbol; i++)
                {
                    automatGridD.Columns.Add("d_col_" + i.ToString(), L.ABC.code(i));
                    automatGridO.Columns.Add("o_col_" + i.ToString(), L.ABC.code(i));
                }
                stop = true;
            }
            if (new_filtron == false && uwaga("All information about defined automate would be lost\nDo you want to continue?") == DialogResult.OK)
            {

                automatGridD.Rows.Clear();
                automatGridO.Rows.Clear();
                automatGridD.Columns.Clear();
                automatGridO.Columns.Clear();
                try
                {
                    fillFiltron();
                    for (int i = 0; i <= L.MaxSymbol; i++)
                    {
                        automatGridD.Columns.Add("d_col_" + i.ToString(), L.ABC.code(i));
                        automatGridO.Columns.Add("o_col_" + i.ToString(), L.ABC.code(i));
                    }
                    object[] rw = new object[automatGridD.ColumnCount];
                    for (int i = 0; i < automatGridD.ColumnCount; i++)
                        rw[i] = "";
                    int new_ee = automatGridD.Rows.Add(rw);
                    int new_ff = automatGridO.Rows.Add(rw);
                    automatGridD.Rows[new_ee].HeaderCell.Value = "0";
                    automatGridO.Rows[new_ff].HeaderCell.Value = "0";
                    btnNextStep.Enabled = true;
                    nextStateCount.Enabled = true;
                    A = new Automat(L.MaxSymbol);
                    //RedefineAutomate();
                    new_filtron = true;
                    filtron_line = 0;
                    filtron_symbol = 0;
                    stop = true;
                    filtronClass.Enabled = true;
                }
                catch (MyErrors er)
                {
                    uwaga(er.Message);
                }

                //makeGraph();
            }
        }
        // realy this function doesn't work, ):
        private void makeGraph()
        {
            
        }
        private void filtronGraphPanel_Paint(object sender, PaintEventArgs e)
        {
           
        }
       

        private void setFiltron_Click(object sender, EventArgs e)
        {
            setFiltron();
            
        }

        private void quitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }
        /// <summary>
        /// use for defining automate from deined filtron. It's not automate process
        /// </summary>
        private void RedefineAutomate()
        {
            /*if (filtroniasty == null)
                throw new Exception("Filtron wasn't defined");
            for (int i = 0; i < filtroniasty.Count-1; i++)
            {
                string[] input_line = filtroniasty[i];
                string[] output_line = filtroniasty[i + 1];
                for (int j = 0; j < input_line.Length; j++)
                {
                    pokoloruj(i, j, Color.Yellow);
                    string input_symbol = input_line[j];
                    string output_symbol = output_line[j];
                    if (A.odpowiedzi.ContainsKey(current_state + 1) == false)
                    {
                        break;
                    }
                }
            }*/
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (pytanie("Do you want to clear everything?") == DialogResult.Yes)
            {
                new_filtron = false;
                btnFiltronClear.Enabled = false;
                btnFiltronSet.Enabled = false;
                btnNextStep.Enabled = false;
                L = null;
                foreach (DataGridViewRow rr in filtronGrid.Rows)
                    foreach (DataGridViewCell cc in rr.Cells)
                    {
                        cc.Value = "0";
                        cc.Style.BackColor = Color.White;
                    }
                A = null;
                hfffOperation = null;
                automatGridD.Rows.Clear();
                automatGridD.Columns.Clear();
                automatGridO.Columns.Clear();
                automatGridO.Rows.Clear();
                nextStateCount.Value = 0;
                groupBox3.Enabled = false;
                cefamHFFFGrid.Rows.Clear();
                cefamHFFFGrid.Columns.Clear();
            }
        }

        private void filtronGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            btnFiltronClear.Enabled = true;
            btnFiltronSet.Enabled = true;
            //btnNextStep.Enabled = true;
            if (new_filtron)
                filtron_edited = true;

        }

        private void pokoloruj(int linia, int kolumna, Color kolor)
        {
            filtronGrid.Rows[linia].Cells[kolumna].Style.BackColor = kolor;
            filtronGrid.Rows[linia + 1].Cells[kolumna].Style.BackColor = kolor;
            if (kolumna == 0 && linia > 0)
            {
                filtronGrid.Rows[linia-1].Cells[filtronGrid.ColumnCount - 1].Style.BackColor = Color.White;
                filtronGrid.Rows[linia].Cells[filtronGrid.ColumnCount - 1].Style.BackColor = Color.White;
            }

            /*if (kolumna == filtronGrid.ColumnCount - 1)
            {
                filtronGrid.Rows[linia].Cells[kolumna].Style.BackColor = Color.White;
                filtronGrid.Rows[linia + 1].Cells[kolumna].Style.BackColor = Color.White;
            }*/
            if (linia >= 0 && linia < filtronGrid.Rows.Count - 1)
                if (kolumna > 0 && kolumna < filtronGrid.Rows[0].Cells.Count)
                {
                    filtronGrid.Rows[linia].Cells[kolumna - 1].Style.BackColor = Color.White;
                    filtronGrid.Rows[linia + 1].Cells[kolumna - 1].Style.BackColor = Color.White;
                }
            if (linia == 0 && kolumna == 0)
            {
                filtronGrid.Rows[filtronGrid.RowCount - 1].Cells[filtronGrid.ColumnCount - 1].Style.BackColor = Color.White;
                filtronGrid.Rows[filtronGrid.RowCount - 2].Cells[filtronGrid.ColumnCount - 1].Style.BackColor = Color.White;
            }
        }
        /// <summary>
        /// All class of filtrons. Generate manual
        /// </summary>
        private void allFiltronsProcess()
        {
            string[] input_line = filtroniasty[filtron_line];
            string[] output_line = filtroniasty[filtron_line + 1];
            int nn_state = Convert.ToInt32(nextStateCount.Value);
            int max_state = 0;
            if (current_state >= nn_state)
                max_state = current_state;
            else
                max_state = nn_state;

            string input_symbol = input_line[filtron_symbol];
            string output_symbol = output_line[filtron_symbol];
            statusBarCharNr.Text = input_symbol;
            statusBarLineNr.Text = output_symbol;
            if (stop)
            {
                input_symbol = input_line[filtron_symbol];
                output_symbol = output_line[filtron_symbol];
                A.set(current_state, A.alp.decode(input_symbol), A.alp.decode(output_symbol), Convert.ToInt32(nextStateCount.Value));

                nextStateCount.Enabled = false;
                if (current_state >= automatGridD.RowCount)
                {
                    for (int i = automatGridD.RowCount; i <= max_state; i++)
                    {
                        object[] rr = new object[automatGridD.ColumnCount - 1];
                        int new_ee = automatGridD.Rows.Add(rr);
                        //int new_ff = automatGridO.Rows.Add(rr);
                        automatGridD.Rows[new_ee].HeaderCell.Value = i.ToString();
                        //automatGridO.Rows[new_ff].HeaderCell.Value = i.ToString();
                    }
                }

                automatGridO.Rows[current_state].Cells[A.alp.decode(input_symbol)].Value = output_symbol;
                automatGridD.Rows[current_state].Cells[A.alp.decode(input_symbol)].Value = nn_state.ToString();

                current_state = nn_state;

                stop = false;
                if (filtron_symbol < filtronGrid.Rows[0].Cells.Count - 1)
                    filtron_symbol++;
                else
                {
                    filtron_symbol = 0;
                    if (filtron_line < filtronGrid.Rows.Count - 2)
                        filtron_line++;
                    else
                        filtron_line = 0;
                }
                pokoloruj(filtron_line, filtron_symbol, Color.YellowGreen);
            }
            input_symbol = input_line[filtron_symbol];
            output_symbol = output_line[filtron_symbol];
            pokoloruj(filtron_line, filtron_symbol, Color.YellowGreen);
            if (A.odpowiedzi.ContainsKey(current_state) == false)
            {
                stop = true;
            }
            else
            {
                int outputFromAutomate = A.odpowiedzi[current_state][A.alp.decode(input_symbol)];
                if (outputFromAutomate == -1)
                {
                    stop = true;
                }
                else
                {
                    if (outputFromAutomate != A.alp.decode(output_symbol))
                        uwaga("Error, defined automate can't process this filtron\n" + "Automate output:" + A.alp.code(A.odpowiedzi[current_state][A.alp.decode(input_symbol)]) + " output from ST:" + output_symbol);
                    else
                        current_state = A.stan_nastepny[current_state][A.alp.decode(input_symbol)];
                }

            }
            statusNext.Text = current_state.ToString();
            

            if (stop == false)
            {
                if (filtron_symbol < filtronGrid.Rows[0].Cells.Count - 1)
                    filtron_symbol++;
                else
                {
                    filtron_symbol = 0;
                    if (filtron_line < filtronGrid.Rows.Count - 2)
                        filtron_line++;
                    else
                    {
                        filtron_line = 0;
                    }
                }

            }
            pokoloruj(filtron_line, filtron_symbol, Color.YellowGreen);
            if (stop)
            {
                nextStateCount.Enabled = true;
                btnNextStep.Enabled = false;
            }
            if (stop)
            {
                if (current_state >= automatGridO.RowCount)
                {
                    for (int i = automatGridO.RowCount; i <= max_state; i++)
                    {
                        object[] rr = new object[automatGridO.ColumnCount - 1];
                        int new_ee = automatGridO.Rows.Add(rr);
                        automatGridO.Rows[new_ee].HeaderCell.Value = i.ToString();
                    }
                }
                if (automatGridO.Rows.Count > current_state)
                    automatGridO.Rows[current_state].Cells[A.alp.decode(input_symbol)].Value = output_symbol;
            }
            /*else
            {
                automatGridO.RowCount = current_state+1;
                automatGridO.Rows[current_state].Cells[A.alp.decode(input_symbol)].Value = output_symbol;
            }*/
        }

        List<string> lastActivateSymbol = new List<string>();

        //global things form cefamMechanizm
        string buffer = "";
        int charCounter = 0;
        bool noErrors = true;
        bool inActiveState = false;
        int segmentCount = 0;
        int varSegment;
        /// <summary>
        /// Fill CEFAM automate, one step
        /// </summary>
        /// <param name="charNr"></param>
        /// <param name="lineNr"></param>
        private void cefamMechanizm(int charNr, int lineNr)
        {
            List<string> active = new List<string>(automateActivateSymbols.Text.Split(','));
            //lastActivateSymbol.Clear();
            string[] inputLine = filtroniasty[lineNr];
            string[] outputLine = filtroniasty[lineNr + 1];
            statusBarLineNr.Text = lineNr.ToString();
            string inputChar = inputLine[charNr];
            statusBarCharNr.Text = charNr.ToString();
            string outputChar = outputLine[charNr];
            //coloring
            pokoloruj(lineNr, charNr, Color.YellowGreen);
            //
            if (active.Contains(inputChar)) // run Forest run Forest
            {
                inActiveState = true;
                if(charCounter == 0)
                    lastActivateSymbol.Add(inputChar);
            }
            statusBarActive.Text = inActiveState.ToString();
            statusBarSegmentNr.Text = segmentCount.ToString();
            if (!inActiveState && charCounter == 0)
            {
                try
                {
                    hfffOperation.PutHOutput(inputChar, outputChar, inputChar);
                }
                catch (MyErrors er)
                {
                    uwaga(er.Message + "\nSomething wrong, contact with author.\nSend this error message:\n"+er.Message);
                }
                int rowNr = L.ABC.decode(inputChar);
                int columnNr = L.ABC.decode(inputChar);
                cefamHFFFGrid.Rows[rowNr].Cells[columnNr].Value = outputChar;
                
            }
            if (inActiveState)
            {
                lastActivateSymbol.Reverse();
                string hOperationSymbol = inputChar;
                if (charCounter == 0)
                {
                    try
                    {
                        if (segmentCount != 0)
                        {
                            //looking for h-sandwich, based on activate symbol
                            bool hasHOperation = hfffOperation.hasHOperation(inputChar);
                            if (hasHOperation == false || inputChar == "0")
                            {
                                string newSymbol = "";
                                foreach (string sy in lastActivateSymbol)
                                {
                                    if (hfffOperation.hasHOperation(sy))
                                    {
                                        newSymbol = sy;
                                        break;
                                    }
                                }
                                hfffOperation.PutHOutput(inputChar, outputChar, newSymbol);
                                hOperationSymbol = newSymbol;
                            }
                            else
                                hfffOperation.PutHOutput(inputChar, outputChar, inputChar);
                        }
                        else
                        {
                            hfffOperation.PutHOutput(inputChar, outputChar, "0");
                            hOperationSymbol = "0";
                        }
                        int rowNr = L.ABC.decode(hOperationSymbol);
                        int columnNr = L.ABC.decode(inputChar);
                        cefamHFFFGrid.Rows[rowNr].Cells[columnNr].Value = outputChar;
                    }
                    catch (MyErrors er)
                    {
                        
                        if (filtronInline.Checked == true)
                        {
                            InputBox nn = new InputBox(er.Message);
                            nn.ShowDialog();
                            string ret = nn.GetAnswer();
                            filtroniasty[lineNr + 1][charNr] = ret;
                            filtronGrid.Rows[lineNr + 1].Cells[charNr].Value = ret;
                            try
                            {
                                if (segmentCount != 0)
                                {
                                    //looking for h-sandwich, based on activate symbol
                                    if (hfffOperation.hasHOperation(inputChar) == false || inputChar == "0")
                                    {
                                        string newSymbol = "";
                                        foreach (string sy in lastActivateSymbol)
                                        {
                                            if (hfffOperation.hasHOperation(sy))
                                            {
                                                newSymbol = sy;
                                                break;
                                            }
                                        }
                                        hfffOperation.PutHOutput(inputChar, ret, newSymbol);
                                        hOperationSymbol = newSymbol;
                                    }
                                    else
                                        hfffOperation.PutHOutput(inputChar, ret, inputChar);
                                }
                                else
                                    hfffOperation.PutHOutput(inputChar, ret, "0");
                                //hfffOperation.PutHOutput(inputChar, ret, inputChar);
                                outputChar = ret;
                                int rowNr = L.ABC.decode(hOperationSymbol);
                                int columnNr = L.ABC.decode(inputChar);
                                cefamHFFFGrid.Rows[rowNr].Cells[columnNr].Value = outputChar;
                            }
                            catch (MyErrors er1)
                            {
                                uwaga("Changes was incorect, can't process this filtron");
                            }
                        }
                        else
                            if (cefamInlineMode.Checked == true)
                            {
                                InputBox nn = new InputBox(er.Message);

                            } else
                                uwaga(er.Message);
                    }


                    //fill operation grid

                }
                if (charCounter != 0)
                {
                    try
                    {
                        /*if (hfffOperation.GetFOutput(inputChar, charCounter - 1) != "" && outputChar == "0")
                        {
                            outputChar = hfffOperation.GetFOutput(inputChar, charCounter - 1);
                            filtroniasty[lineNr + 1][charNr] = outputChar;
                            filtronGrid.Rows[lineNr + 1].Cells[charNr].Value = outputChar;
                        }
                        else*/
                        hfffOperation.PutFOutput(inputChar, outputChar, charCounter - 1);
                        int rowNr = L.MaxSymbol + charCounter;
                        int columnNr = L.ABC.decode(inputChar);
                        cefamHFFFGrid.Rows[rowNr].Cells[columnNr].Value = outputChar;
                    }
                    catch (MyErrors er)
                    {
                        if (filtronInline.Checked == true)
                        {
                            InputBox nn = new InputBox(er.Message);
                            nn.ShowDialog();
                            string ret = nn.GetAnswer();
                            filtroniasty[lineNr + 1][charNr] = ret;
                            filtronGrid.Rows[lineNr + 1].Cells[charNr].Value = ret;
                            try
                            {
                                hfffOperation.PutFOutput(inputChar, ret, charCounter - 1);
                                outputChar = ret;
                                int rowNr = L.MaxSymbol + charCounter;
                                int columnNr = L.ABC.decode(inputChar);
                                cefamHFFFGrid.Rows[rowNr].Cells[columnNr].Value = outputChar;
                            }
                            catch (MyErrors er1)
                            {
                                uwaga("Change was incorect, can't process this filtron");
                            }
                        }
                        else
                            uwaga(er.Message);
                    }

                }
                if (buffer.Length >= kSegment.Value)
                    buffer = "";
                lastActivateSymbol.Reverse();
            }
            if (inActiveState)
            {
                buffer += inputChar;
                if (buffer.Length == varSegment) // #ok so we can disable automate using non constanst length of disable sequence
                    foreach (Regex r in extinctionRegex)
                        if (inActiveState)
                        {
                            inActiveState = (!r.IsMatch(buffer));
                            if (!inActiveState)
                                segmentCount = 0;
                        }
            }
            if (inActiveState && (charCounter < kSegment.Value - 1))
                charCounter++;
            else
            {
                charCounter = 0;
                if (inActiveState)
                    segmentCount++;
            }
     
        
        }

        /// <summary>
        /// Only for sandwiches state automate
        /// </summary>
        private void fsmFiltronsProcess()
        {
            //ugly but deadline is comming up very fast
            varSegment = (int)kSegment.Value;
            foreach (string st in automateExtinction.Items)
                if (varSegment > st.Length)
                    varSegment = st.Length;
            buffer = "";
            charCounter = 0;
            noErrors = true;
            inActiveState = false;
            segmentCount = 0;
            lastActivateSymbol.Clear();
            for(int lineNr = 0; lineNr < filtroniasty.Count-1; lineNr++)
            {
                filtron_line = lineNr;
                for (int charNr = 0; charNr < filtroniasty[lineNr].Length; charNr++)
                {
                    filtron_symbol = charNr;
                    cefamMechanizm(charNr,lineNr);
                }
            }
        }

        private void button1_Click(object sender, EventArgs e) // next button
        {
            if (filtronClass.SelectedIndex == 0)
                allFiltronsProcess();
            if (filtronClass.SelectedIndex == 1)
                fsmFiltronsProcess();
        }

        //bool firstStep = true;

        private void cefamStepBtn_Click(object sender, EventArgs e) // step mode for CEFAM automate. global automate only in this mode
        {
            if (filtron_symbol == 0 && filtron_line == 0)
            {
                varSegment = (int)kSegment.Value;
                foreach (string st in automateExtinction.Items)
                    if (varSegment > st.Length)
                        varSegment = st.Length;
                buffer = "";
                charCounter = 0;
                noErrors = true;
                inActiveState = false;
                segmentCount = 0;
                lastActivateSymbol.Clear();
                //firstStep = false;
                filtron_line = 0;
                filtron_symbol = 0;
            }
            cefamMechanizm(filtron_symbol, filtron_line);
            if (filtron_symbol == filtroniasty[filtron_line].Length - 1)
            {
                if (filtron_line+1 >= filtroniasty.Count-1)
                    filtron_line = 0;
                else
                    filtron_line++;
                filtron_symbol = 0;
            }
            else
            {
                filtron_symbol++;
            }
            
        }
        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void Form1_Load(object sender, EventArgs e)
        {
            object[] rw = new object[filtronGrid.ColumnCount];
            //rw.SetValue(" ", 0);
            for (int i = 0; i < filtronGrid.ColumnCount; i++)
                rw[i] = 0;
            if (filtronGridY.Value > filtronGrid.Rows.Count)
                filtronGrid.Rows.Add(rw);
        }

        private void cefamSaveProcedure(StreamWriter ww)
        {
            List<string> active = new List<string>(automateActivateSymbols.Text.Split(','));
            CEFAM cefamFile = new CEFAM(hfffOperation, extinctionRegex, active, Convert.ToInt32(kSegment.Value));
            foreach (string lin in cefamFile.GetFile())
                ww.WriteLine(lin);
            ww.Close();
        }

        private void saveFiltronToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (saveFile.ShowDialog() == DialogResult.OK)
            {
                StreamWriter sw = new StreamWriter(saveFile.FileName);

                    foreach (DataGridViewRow rr in filtronGrid.Rows)
                    {
                        string line = "";
                        //List<string> line = new List<string>();
                        foreach (DataGridViewCell cc in rr.Cells)
                        {
                            line += cc.Value.ToString();
                        }
                        sw.WriteLine(line);
                    }
                    sw.Close();
                
            }
        }


        private void loadFiltronToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (uwaga("All data would be lost.\nDo you want to continue?") == DialogResult.OK)
            {
                if (openFile.ShowDialog() == DialogResult.OK)
                {
                    filtronFromFile = true;
                    StreamReader sr = new StreamReader(openFile.FileName, Encoding.ASCII);
                    filtronGrid.Rows.Clear();
                    //filtronGridY.Value = Convert.ToDecimal(sw.BaseStream.Length);
                    try
                    {
                        string first_line = sr.ReadLine();
                        filtronGridX.Value = Convert.ToDecimal(first_line.Length);
                        filtronGrid.ColumnCount = Convert.ToInt32(first_line.Length);
                        List<string> fuckedOutput = new List<string>();
                        foreach(char z in first_line)
                            fuckedOutput.Add(z.ToString());
                        filtronGrid.Rows.Add(fuckedOutput.ToArray());
                        string line;
                        while ((line = sr.ReadLine()) != null)
                        {
                            fuckedOutput.Clear();
                            foreach (char z in line)
                                fuckedOutput.Add(z.ToString());
                            filtronGrid.Rows.Add(fuckedOutput.ToArray());
                            filtronGridY.Value++;
                        }
                        sr.Close();
                        setFiltron();
                        new_filtron = true;
                        filtronFromFile = false;
                    }
                    catch (MyErrors st)
                    {
                       uwaga(st.Message);
                    }
                }
            }
        }
        
        private void automatGridD_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            //string chan = automatGridD.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
            //if (chan == "")
            //    chan = "-";
            //A.stan_nastepny[e.RowIndex][e.ColumnIndex] = Convert.ToInt32(A.alp.decode(chan));

            object cell = automatGridD.SelectedCells[0].Value;
            //string chan = automatGridO.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
            string chan = cell.ToString();
            if (chan == "")
                chan = "-";
            A.odpowiedzi[automatGridD.SelectedCells[0].RowIndex][automatGridD.SelectedCells[0].ColumnIndex] = Convert.ToInt32(A.alp.decode(chan));
        }

        private void automatGridO_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            object cell = automatGridO.SelectedCells[0].Value;
            //string chan = automatGridO.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
            string chan = cell.ToString();
            if (chan == "")
                chan = "-";
            A.odpowiedzi[automatGridO.SelectedCells[0].RowIndex][automatGridO.SelectedCells[0].ColumnIndex] = Convert.ToInt32(A.alp.decode(chan));
        }

        private void saveAutomateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (saveFile.ShowDialog() == DialogResult.OK)
            {
                StreamWriter sw = new StreamWriter(saveFile.FileName);
                if (filtronClass.SelectedIndex == 1)
                    cefamSaveProcedure(sw);
                else
                {
                    MlFile parserFile = new MlFile(A.stan_nastepny, A.odpowiedzi);
                    
                    foreach (string d in parserFile.GetFile())
                    {
                        sw.WriteLine(d);
                    }
                    sw.Close();
                }
            }
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox1 a = new AboutBox1();
            a.ShowDialog();
        }

        private void nextStateCount_Click(object sender, EventArgs e)
        {
            btnNextStep.Enabled = true;
        }

        private void RefreshAutomateGrid(MlFile mll)
        {
            automatGridD.Rows.Clear();
            automatGridO.Rows.Clear();
            foreach (KeyValuePair<int, Dictionary<int, int>> key in A.stan_nastepny)
            {
                List<object> obj = new List<object>();
                automatGridD.ColumnCount = key.Value.Count;
                foreach (KeyValuePair<int, int> dsa in key.Value)
                {
                    obj.Add(A.alp.code(dsa.Value));
                    automatGridD.Columns[dsa.Key].HeaderText = A.alp.code(dsa.Key);
                }
                
                int new_ee = automatGridD.Rows.Add(obj.ToArray());
                automatGridD.Rows[new_ee].HeaderCell.Value = key.Key.ToString();
            }
            foreach (KeyValuePair<int, Dictionary<int, int>> key in A.odpowiedzi)
            {
                List<object> obj = new List<object>();
                automatGridO.ColumnCount = key.Value.Count;
                foreach (KeyValuePair<int, int> dsa in key.Value)
                {
                    obj.Add(A.alp.code(dsa.Value));
                    automatGridO.Columns[dsa.Key].HeaderText = A.alp.code(dsa.Key);
                }
                //automatGridO.ColumnCount = key.Value.Count - 1;
                int new_ee = automatGridO.Rows.Add(obj.ToArray());
                automatGridO.Rows[new_ee].HeaderCell.Value = key.Key.ToString();
            }
        }

        private void loadCEFAM(string[] cefam)
        {
            try
            {
                CEFAM cef = new CEFAM(cefam);
                hfffOperation = cef.GetOperation;
                kSegment.Value = cef.GetSegmentSize;
                //hfffOperation = new OperationSet(Convert.ToInt32(kSegment.Value), L.MaxSymbol);
                cefamHFFFGrid.Rows.Clear();
                cefamHFFFGrid.Columns.Clear();
                
                for (int i = 0; i <= L.MaxSymbol; i++)
                {
                    cefamHFFFGrid.Columns.Add("cefam_col_" + i.ToString(), L.ABC.code(i));
                    DataGridViewRow rr = new DataGridViewRow();
                    rr.HeaderCell.Value = "h" + L.ABC.code(i) + "=";
                    rr.DefaultCellStyle.BackColor = Color.White;
                    cefamHFFFGrid.Rows.Add(rr);
                }
                for (int i = 1; i <= Convert.ToInt32(kSegment.Value) - 1; i++)
                {
                    DataGridViewRow rr = new DataGridViewRow();
                    rr.HeaderCell.Value = "f" + L.ABC.code(i) + "=";
                    rr.DefaultCellStyle.BackColor = Color.White;
                    cefamHFFFGrid.Rows.Add(rr);
                }
                btnNextStep.Enabled = false;
                extinctionRegex.Clear();
                foreach (Regex x in cef.GetExtinction)
                {
                    automateExtinction.Items.Add(x.ToString().Replace('?', '*').TrimStart('^'));
                }
                automateActivateSymbols.Text = "";
                foreach (string s in cef.GetActivate)
                {
                    automateActivateSymbols.Text += s + ",";
                }
                for (int y = 0; y < cef.Grid.Count; y++)
                {
                    for (int x = 0; x < cef.Grid[y].Count; x++)
                    {
                        if (cef.Grid[y][x] != "-")
                        {
                            cefamHFFFGrid.Rows[y].Cells[x].Value = cef.Grid[y][x];
                        }
                    }
                }
                automateActivateSymbols.Text = automateActivateSymbols.Text.TrimEnd(',');
                extinctionRegex = cef.GetExtinction;
                btnNextStep.Enabled = true;
                btnNextStep.Text = "Go";
                cefamStepBtn.Enabled = true;
            }
            catch (MyErrors er)
            {
                uwaga(er.Message);
            }

        }

        private void loadAutomateToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (uwaga("Information about automate would be lost.") == DialogResult.OK)
            {
                if (openFile.ShowDialog() == DialogResult.OK && filtronClass.SelectedIndex != -1)
                {
                    StreamReader sr = new StreamReader(openFile.FileName);
                    
                    //filtronGridY.Value = Convert.ToDecimal(sw.BaseStream.Length);
                    string line;
                    try
                    {
                        List<string> st = new List<string>();
                        while ((line = sr.ReadLine()) != null)
                        {
                            st.Add(line);
                        }
                        if (filtronClass.SelectedIndex == 1)
                        {
                            loadCEFAM(st.ToArray());
                        }
                        else
                        {
                            filtronGrid.Rows.Clear();
                            MlFile ml = new MlFile(st.ToArray());
                            A = new Automat(ml.NextStates, ml.Outputs);
                            RefreshAutomateGrid(ml);
                        }
                    }
                    catch (MyErrors es)
                    {
                        uwaga(es.Message);
                    }
                    sr.Close();
                }
            }
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            foreach (DataGridViewRow rr in automatGridO.Rows)
            {
                foreach (DataGridViewCell cc in rr.Cells)
                {
                    if (cc.Value == null || cc.Value.ToString() == "")
                        A.odpowiedzi[cc.RowIndex][cc.ColumnIndex] = -1;
                        //A.set(cc.RowIndex, cc.ColumnIndex, -1, automatGridD.Rows[cc.RowIndex].Cells[cc.ColumnIndex].Value);
                    else
                        //A.set(cc.RowIndex, cc.ColumnIndex, A.alp.decode(cc.Value.ToString()), automatGridD.Rows[cc.RowIndex].Cells[cc.ColumnIndex].Value);
                        A.odpowiedzi[cc.RowIndex][cc.ColumnIndex] = A.alp.decode(cc.Value.ToString());
                }
            }
            foreach (DataGridViewRow rr in automatGridD.Rows)
            {
                foreach (DataGridViewCell cc in rr.Cells)
                {
                    if (cc.Value == null || cc.Value.ToString() == "")
                        A.stan_nastepny[cc.RowIndex][cc.ColumnIndex] = -1;
                        
                    else
                        A.stan_nastepny[cc.RowIndex][cc.ColumnIndex] = A.alp.decode(cc.Value.ToString());
                }
            }
        }

        private object cellFiltronState;

        private void filtronGrid_CellBeginEdit(object sender, DataGridViewCellCancelEventArgs e)
        {
            
        }
        /// <summary>
        /// off
        /// </summary>
        public void predictKSegment()
        {
            int segmentCount = 0;
            for (int lineNr = 0; lineNr < filtroniasty.Count; lineNr++)
            {
                string[] inputLine = filtroniasty[lineNr];
                for (int charNr = 0; charNr < inputLine.Length; charNr++)
                {
                    string inputChar = inputLine[charNr];
                    if (inputChar != "0")
                    {
                        segmentCount++;
                    }
                }

            }
        }

        private void automateActivateSymbolsFill()
        {
            automateActivateSymbols.Text = "";
            for (int i = 0; i <= L.MaxSymbol; i++)
            {
                automateActivateSymbols.Text += L.ABC.code(i) + ",";
                
            }
            automateActivateSymbols.Text = automateActivateSymbols.Text.TrimEnd(',');
            automateActivateSymbols.Text = automateActivateSymbols.Text.TrimStart('0');
            automateActivateSymbols.Text = automateActivateSymbols.Text.TrimStart(',');
        }

        private void filtronClass_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (filtronClass.SelectedIndex)
            {
                case 0:
                    filtronFSMGroupOptions.Visible = false;
                    filtronALLOptionsGroup.Visible = true;
                    optionsTab.SelectedTab = fsmTAB;
                    btnNextStep.Enabled = true;
                    nextStateCount.Enabled = true;
                    //fsmTAB.Show();
                    filtronInline.Visible = false;
                    btnNextStep.Text = "Next";
                    cefamStepBtn.Visible = false;
                    optionsTab.Enabled = true;
                    break;
                case 1:
                    filtronALLOptionsGroup.Visible = false;
                    filtronFSMGroupOptions.Visible = true;
                    optionsTab.SelectedTab = cefamAutomate;
                    automateActivateSymbolsFill();
                    //fsmTAB.Hide();
                    filtronInline.Visible = true;
                    btnNextStep.Text = "Go";
                    btnNextStep.Enabled = false;
                    //predictKSegment();
                    cefamStepBtn.Visible = true;
                    optionsTab.Enabled = true;
                    break;
            }
            loadAutomateToolStripMenuItem.Enabled = true;
            saveAutomateToolStripMenuItem.Enabled = true;

        }

        private void filtronFSMSetK_Click(object sender, EventArgs e)
        {
            
            if (cefamHFFFGrid.Rows.Count == 0)
            {
                hfffOperation = new OperationSet(Convert.ToInt32(kSegment.Value), L.MaxSymbol, ref statusBarHLayerNr, ref statusBarFLayerNr);
                cefamHFFFGrid.Rows.Clear();
                cefamHFFFGrid.Columns.Clear();

                for (int i = 0; i <= L.MaxSymbol; i++)
                {
                    cefamHFFFGrid.Columns.Add("cefam_col_" + i.ToString(), L.ABC.code(i));
                    DataGridViewRow rr = new DataGridViewRow();
                    rr.HeaderCell.Value = "h" + L.ABC.code(i) + "=";
                    rr.DefaultCellStyle.BackColor = Color.White;
                    cefamHFFFGrid.Rows.Add(rr);
                }
                for (int i = 1; i <= Convert.ToInt32(kSegment.Value) - 1; i++)
                {
                    DataGridViewRow rr = new DataGridViewRow();
                    rr.HeaderCell.Value = "f" + L.ABC.code(i) + "=";
                    rr.DefaultCellStyle.BackColor = Color.White;
                    cefamHFFFGrid.Rows.Add(rr);
                }
            }
            else
            {
                if (hfffOperation.StateCount < L.MaxSymbol)
                {
                    for (int i = hfffOperation.StateCount+1; i <= L.MaxSymbol; i++)
                    {
                        cefamHFFFGrid.Columns.Add("cefam_col_" + i.ToString(), L.ABC.code(i));
                        DataGridViewRow rr = new DataGridViewRow();
                        rr.HeaderCell.Value = "h" + L.ABC.code(i) + "=";
                        rr.DefaultCellStyle.BackColor = Color.White;
                        cefamHFFFGrid.Rows.Insert(i, rr);
                    }
                }
                if (hfffOperation.SegmentSize < Convert.ToInt32(kSegment.Value))
                {
                    for (int i = hfffOperation.SegmentSize; i <= Convert.ToInt32(kSegment.Value) - 1; i++)
                    {
                        DataGridViewRow rr = new DataGridViewRow();
                        rr.HeaderCell.Value = "f" + L.ABC.code(i) + "=";
                        rr.DefaultCellStyle.BackColor = Color.White;
                        cefamHFFFGrid.Rows.Add(rr);
                    }
                }
                else
                {
                    for (int i = Convert.ToInt32(kSegment.Value); i < hfffOperation.SegmentSize; i++)
                    {
                        cefamHFFFGrid.Rows.RemoveAt(i);
                    }
                }
                hfffOperation.changeSettings(Convert.ToInt32(kSegment.Value), L.MaxSymbol);
            }
            groupBox3.Enabled = true;
            clearCEFAM.Enabled = true;
            if (automateExtinction.Items.Count == 0)
                btnNextStep.Enabled = false;
            else
                btnNextStep.Enabled = true;
            /*for (int i = 0; i <= L.MaxSymbol; i++)
            {
                automateActivateSymbols.Text += L.ABC.code(i) + ",";
            }*/
        }

        private void inputExtinction_KeyPress(object sender, KeyPressEventArgs e)
        {
            if(e.KeyChar == (char)Keys.Enter)
                if (inputExtinction.Text != "")
                {
                    if (!automateExtinction.Items.Contains(inputExtinction.Text))
                    {
                        automateExtinction.Items.Add(inputExtinction.Text);
                        inputExtinction.Text = "";
                        extinctionRegex.Clear();
                        foreach (string st in automateExtinction.Items)
                        {
                            Regex rr = new Regex("^" + st.Replace('*', '?'));
                            extinctionRegex.Add(rr);
                        }
                        if (automateExtinction.Items.Count > 0)
                        {
                            btnNextStep.Enabled = true;
                            cefamStepBtn.Enabled = true;
                        }
                    }
                }
        }

        private void automateExtinction_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (e.KeyChar == (char)Keys.Back)
                if(automateExtinction.SelectedIndex > -1)
                    automateExtinction.Items.RemoveAt(automateExtinction.SelectedIndex);
        }

        private void button2_Click_1(object sender, EventArgs e) // set extinction
        {

        }

        private void kSegment_ValueChanged(object sender, EventArgs e)
        {

        }

        private void optionsTab_Selected(object sender, TabControlEventArgs e)
        {
            optionsTab.SelectedIndex = filtronClass.SelectedIndex;
        }

        private void automateExtinction_Leave(object sender, EventArgs e)
        {

        }

        private void toolStripStatusLabel6_Click(object sender, EventArgs e)
        {

        }

        private void cefamHFFFGrid_UserDeletedRow(object sender, DataGridViewRowEventArgs e)
        {
            
        }

        private void clearCEFAM_Click(object sender, EventArgs e)
        {
            if (pytanie("Do you want to clear defined automate?") == DialogResult.Yes)
            {
                hfffOperation = new OperationSet(Convert.ToInt32(kSegment.Value), L.MaxSymbol, ref statusBarHLayerNr, ref statusBarFLayerNr);
                cefamHFFFGrid.Rows.Clear();
                cefamHFFFGrid.Columns.Clear();
                automateActivateSymbols.Text = "";
                for (int i = 0; i <= L.MaxSymbol; i++)
                {
                    cefamHFFFGrid.Columns.Add("cefam_col_" + i.ToString(), L.ABC.code(i));
                    DataGridViewRow rr = new DataGridViewRow();
                    rr.HeaderCell.Value = "h" + L.ABC.code(i) + "=";
                    rr.DefaultCellStyle.BackColor = Color.White;
                    cefamHFFFGrid.Rows.Add(rr);
                }
                for (int i = 1; i <= Convert.ToInt32(kSegment.Value) - 1; i++)
                {
                    DataGridViewRow rr = new DataGridViewRow();
                    rr.HeaderCell.Value = "f" + L.ABC.code(i) + "=";
                    rr.DefaultCellStyle.BackColor = Color.White;
                    cefamHFFFGrid.Rows.Add(rr);
                }
                automateActivateSymbolsFill();
            }
        }

        private void cefamHFFFGrid_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            
            string column = L.ABC.code(e.ColumnIndex);
            string newValue = cefamHFFFGrid.Rows[e.RowIndex].Cells[e.ColumnIndex].Value.ToString();
            if (newValue != null)
            {
                if (e.RowIndex <= L.MaxSymbol)
                {
                    string jSymbol = L.ABC.code(e.RowIndex);
                    hfffOperation.ChangeHOutput(column, newValue, jSymbol);
                }
                else
                {
                    int jSymbol = (e.RowIndex - L.MaxSymbol - 1);
                    hfffOperation.ChangeFOutput(column, newValue, jSymbol);
                }
            }
        }

        private void cefamHFFFGrid_CellValueChanged(object sender, DataGridViewCellEventArgs e)
        {
            
        }

        private void automatGridD_CellEndEdit_1(object sender, DataGridViewCellEventArgs e)
        {
            if (automatGridD.Rows[e.RowIndex].Cells[e.ColumnIndex].Value != null)
            {
                if (Convert.ToInt16(automatGridD.Rows[e.RowIndex].Cells[e.ColumnIndex].Value) >= automatGridD.Rows.Count)
                {
                    int nowCount = automatGridD.Rows.Count;
                    for (int i = automatGridD.RowCount; i <= Convert.ToInt16(automatGridD.Rows[e.RowIndex].Cells[e.ColumnIndex].Value); i++)
                    {
                        object[] rr = new object[automatGridD.ColumnCount - 1];
                        int new_ee = automatGridD.Rows.Add(rr);
                        //int new_ff = automatGridO.Rows.Add(rr);
                        automatGridD.Rows[new_ee].HeaderCell.Value = i.ToString();
                        //automatGridO.Rows[new_ff].HeaderCell.Value = i.ToString();
                    }
                }
            }
        }

        private void faClearBtn_Click(object sender, EventArgs e)
        {
            if (pytanie("Do you want to clear automate?") == DialogResult.Yes)
            {
                automatGridD.Rows.Clear();
                automatGridO.Rows.Clear();
                automatGridD.Columns.Clear();
                automatGridO.Columns.Clear();
                for (int i = 0; i <= L.MaxSymbol; i++)
                {
                    automatGridD.Columns.Add("d_col_" + i.ToString(), L.ABC.code(i));
                    automatGridO.Columns.Add("o_col_" + i.ToString(), L.ABC.code(i));
                }
                object[] rw = new object[automatGridD.ColumnCount];
                for (int i = 0; i < automatGridD.ColumnCount; i++)
                    rw[i] = "";
                int new_ee = automatGridD.Rows.Add(rw);
                int new_ff = automatGridO.Rows.Add(rw);
                automatGridD.Rows[new_ee].HeaderCell.Value = "0";
                automatGridO.Rows[new_ff].HeaderCell.Value = "0";
                A = new Automat(L.MaxSymbol);
            }
        }

        private void filtronInline_CheckedChanged(object sender, EventArgs e)
        {
            if (cefamInlineMode.Checked == true && filtronInline.Checked == true)
                cefamInlineMode.Checked = false;

        }

        private void cefamInlineMode_CheckedChanged(object sender, EventArgs e)
        {
            if (cefamInlineMode.Checked == true && filtronInline.Checked == true)
                filtronInline.Checked = false;
        }


    }
}
